﻿/**
 * author:  Martin Hrabos
 * year:    2016
 * email:   hrabosmartin@gmail.com
 * 
 * FIT Brno University of Technology / ASCR Brno
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CorrCL
{
    /*
     * Class for storing GPU source code
     */
    static class KernelSources
    {


        public static string getPearsonSources() {

            string code = @"__kernel void Pearson(__global float* x, 

                      __global float* y,
                      __global float* result,

                      const long offset,

                      const long size,

                      const long myIdx)
{
                int idx = get_global_id(0) + myIdx;
                int resultIdx = 0;
                int localIdx = 0;

                if (idx == 0)
                {
                    resultIdx = offset;
                    localIdx = 0;
                }
                else if (idx <= offset)
                {
                    resultIdx = (idx - offset) * (-1);
                    localIdx = idx;
                }
                else if (idx > offset)
                {
                    resultIdx = idx;
                    localIdx = idx - offset;
                }

                if (resultIdx >= 2 * offset + 1)
                    return;

                float meanX;
                float meanY;
                float sumX;
                float sumY;
                float sumXX;
                float sumYY;
                float sumXY;
                meanX = 0.0;
                meanY = 0.0;
                sumX = 0.0;
                sumY = 0.0;
                sumXX = 0.0;
                sumYY = 0.0;
                sumXY = 0.0;

                if (idx <= offset)
                {
                    int i = 0;
                    float actX = 0.0;
                    float actY = 0.0;
                    for (i = 0; i < size - localIdx; i++)
                    {
                        actX = x[i];
                        actY = y[i + localIdx];
                        sumX += actX;
                        sumXX += actX * actX;
                        sumY += actY;
                        sumYY += actY * actY;
                        sumXY += actX * actY;

                    }

                    meanX = sumX / i;
                    meanY = sumY / i;
                    float res = ((sumXY / i) - (meanX * meanY)) / ((sqrt((sumXX / i) - (meanX * meanX))) * (sqrt((sumYY / i) - (meanY * meanY))));
                    if (isnan(res))
                        res = 0.0;
                    result[resultIdx] = res;
                    //result[resultIdx] = 0.5;

                }
                else if (idx > offset)
                {
                    int i = 0;
                    float actX = 0.0;
                    float actY = 0.0;
                    for (i = 0; i < size - localIdx; i++)
                    {
                        actX = x[i + localIdx];
                        actY = y[i];
                        sumX += actX;
                        sumXX += actX * actX;
                        sumY += actY;
                        sumYY += actY * actY;
                        sumXY += actX * actY;
                    }

                    meanX = sumX / i;
                    meanY = sumY / i;
                    float res = ((sumXY / i) - (meanX * meanY)) / ((sqrt((sumXX / i) - (meanX * meanX))) * (sqrt((sumYY / i) - (meanY * meanY))));
                    if (isnan(res))
                        res = 0.0;
                    result[resultIdx] = res;
                    //result[resultIdx] = 0.5;
                }
            }
            ";

            return code;

        }
    }
}
